import {
  ForbiddenException,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import mongoose, { FilterQuery, Model } from 'mongoose';
import { User } from '../entities/user.entity';
import { SignonDto } from '../dto/auth/login-user.dto';
import { JwtService } from '@nestjs/jwt';
import { UpdateUserDto } from '../dto/user/update-user.dto';
import common from '../menu/common';
import global from '../menu/global';
import auth from '../menu/auth';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User.name) private userModel: Model<User>,
    private jwt: JwtService,
  ) {}

  // 登录查询(auth.service.ts使用)
  async findUserLogin(user: SignonDto): Promise<any> {
    const { phone, password } = user;
    let res = await this.userModel.findOne(
      { phone, password, isStatus: true },
      { phone: 1, _id: 1, imgUrl: 1, nick: 1, isAdmin: 1 },
    );
    const { isAdmin } = res;
    if (res) {
      return {
        userInfo: res,
        menu: isAdmin ? [common, global, auth] : [common],
      };
    } else throw new UnauthorizedException('用户名或密码错误');
  }

  // 获取表格用户数据
  async getUsers(
    pageNum: number = 1,
    pageSize: number = 10,
    keyword?: string,
  ): Promise<{
    total: number;
    users: User[];
  }> {
    let idQuery;
    try {
      idQuery = { _id: new mongoose.Types.ObjectId(keyword) };
    } catch {}
    let query: FilterQuery<any> = {};
    if (keyword) {
      query.$or = [
        ...(idQuery ? [idQuery] : []),
        { nick: { $regex: keyword, $options: 'i' } },
        { phone: { $regex: keyword, $options: 'i' } },
      ];
    }

    let total = await this.userModel.countDocuments(query);
    let users = await this.userModel
      .find(query, { token: 0, isAdmin: 0 })
      .skip((pageNum - 1) * pageSize)
      .limit(pageSize)
      .sort({ _id: -1 });

    return { users, total };
  }

  // 新增用户
  async createUser(user: Partial<User>): Promise<User> {
    let canCreate = await this.userModel.findOne({ phone: user.phone });
    if (canCreate) {
      throw new ForbiddenException('该手机号已注册');
    }
    let token = await this.jwt.signAsync(
      {
        phone: user.phone,
        WaiFCode: 'WaiFCode' + user.phone,
      },
      {
        expiresIn: '1d', // 局部设置过期时间
      },
    );
    Object.assign(user, { WaiFCode: 'WaiFCode' + user.phone, token });
    const newUser = this.userModel.create(user);
    return newUser;
  }

  // 更新用户
  async updateUser(
    user: Partial<UpdateUserDto> | User,
  ): Promise<mongoose.UpdateWriteOpResult> {
    // 前端传来需要更新的数据
    const { _id, phone, sign, imgUrl } = user as UpdateUserDto;
    !imgUrl && Object.assign(user, { imgUrl: '/user_pic.png' });
    !sign && Object.assign(user, { sign: '这个人很高冷, 暂时没有留下什么' });
    // 查询该手机号是否被注册
    let canCreate = await this.userModel.findOne({ phone: user.phone });
    if (canCreate) {
      const { _id: saveId, phone: savePhone } = canCreate;
      if (savePhone === phone && saveId.toString() !== _id && canCreate) {
        throw new ForbiddenException('该手机号已注册');
      }
    }
    let updateUser = await this.userModel.updateOne({ _id }, { ...user });
    return updateUser;
  }

  // 删除用户
  async deleteUser(id: string): Promise<mongoose.mongo.DeleteResult> {
    let deleteUser = await this.userModel.deleteOne({ _id: id });
    return deleteUser;
  }

  // 管理员页面获取用户数据
  async adminGetUsers(
    pageNum: number = 1,
    pageSize: number = 10,
    keyword?: string,
  ): Promise<{
    total: number;
    users: User[];
  }> {
    let idQuery;
    try {
      idQuery = { _id: new mongoose.Types.ObjectId(keyword) };
    } catch {}
    let query: FilterQuery<any> = {};
    if (keyword) {
      query.$or = [
        ...(idQuery ? [idQuery] : []),
        { nick: { $regex: keyword, $options: 'i' } },
      ];
    }

    let users = await this.userModel
      .find(query, { _id: 1, nick: 1, isAdmin: 1 })
      .skip((pageNum - 1) * pageSize)
      .limit(pageSize);
    let total = await this.userModel.countDocuments();
    return { users, total };
  }

  // 更新用户权限
  async adminUpdateUser({
    _id,
    isAdmin,
  }: {
    _id: string;
    isAdmin: string;
  }): Promise<mongoose.UpdateWriteOpResult> {
    return await this.userModel.updateOne({ _id }, { isAdmin });
  }
}
